/*
 * Copyright (c) 2007 T.Cogghe, D.Leroux, S.Lévignac, S.Rives
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef __TETE_CHERCHEUSE_H__
#define __TETE_CHERCHEUSE_H__

/** itère dans une image en traçant une spirale
 */

#define TAILLEMAX 32

#define H 0
#define D 1
#define B 2
#define G 3

class TeteChercheuse {
private:

	Position p,ptp;
	int delta;	// longueur de la branche courante
	int i;
	int etat;
	int max;

public:
	TeteChercheuse(int m) : max(m) { delta=i=1; etat=p.x=p.y=0; }
	~TeteChercheuse() {}

	void raz() { p.x=p.y=0; delta=i=1; etat=H; }
	int aFini() { return delta>=max; }

	bool suivant() {
		switch(etat) {
			case H: p.y-=1; break;
			case B: p.y+=1; break;
			case G: p.x-=1; break;
			case D: p.x+=1; break;
		};
		i--;
		if(i==0) {
			etat+=1;
			etat&=3;
			if(etat==H||etat==B) {
				delta++;
			}
			i=delta;
		}
		return delta<max;
	}

	Position& pos() { return p; }
	Position& operator*() { return p; }

	Position& posTourPrec() {
		if(delta<3) {
			ptp.x=ptp.y=0;
		} else if(i==delta) {	/* depuis un coin */
			switch(etat) {
				case H: ptp.x=p.x+1; ptp.y=p.y-1; break;
				case D: ptp.x=p.x+1; ptp.y=p.y+1; break;
				case B: ptp.x=p.x-1; ptp.y=p.y+1; break;
				case G: ptp.x=p.x-1; ptp.y=p.y-1; break;
			};
		} else {		/* depuis un bord */
			switch(etat) {
				case H: ptp.x=p.x+1; ptp.y=p.y; break;
				case D: ptp.x=p.x; ptp.y=p.y+1; break;
				case B: ptp.x=p.x-1; ptp.y=p.y; break;
				case G: ptp.x=p.x; ptp.y=p.y-1; break;
			};
		}
		return ptp;
	}

	/* pour pouvoir tracer le cadre, à n pixels de distance du *bord* */
	Position&posTourSuiv(int n) {
		posTourPrec();
		/* récupère le delta sans trop s'embêter */
		ptp.x=p.x+(p.x-ptp.x)*n;
		ptp.y=p.y+(p.y-ptp.y)*n;
		return ptp;
	}
};



#endif
